home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / PASCAL / DRVTYP20.ZIP / DRVTYPES.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-03-08  |  13.2 KB  |  464 lines

  1. { --------------------------------------------------------------------------- }
  2. { DRVTYPES.PAS  Drive type detection unit.             Version 2.00 }
  3. {                                                                             }
  4. { *** PUBLIC DOMAIN ***                                                       }
  5. { *** THERE ARE NO WARRANTIES PROVIDED AND AS-IS BASIS IS ASSUMED ***         }
  6. {                                                                             }
  7. { Initially written, placed in public domain, detection of Norton Diskreet    }
  8. {  and SuperStor drives in assembly language by Mr. Byte.                     }
  9. { Network drive detection fix, Stacker 4, DoubleDisk and                      }
  10. {  Bernoully drive detection by Bobby Z.                                      }
  11. { RAM drive detection by Janis Smits.                                         }
  12. { Diskreet, SuperStor detection code donated by Vitaly Lysenko                }
  13. { --------------------------------------------------------------------------- }
  14. { History:
  15.  
  16.     mid November, 1994  -  initially released
  17.          29 November, 1994  -  fixed network drive detection and added
  18.                    Stacker 4 drive detection
  19.          10 December, 1994  -  added Janis's RAM drive detection method
  20.      16 January,  1995  -  added Vertisoft DoubleDisk 2.6 drive detection
  21.      31 January,  1995  -  added Bernoully drive detection
  22.           4 February, 1995  -  added Norton Diskreet drive detection
  23.       5 February, 1995  -  added SuperStor drive detection algo
  24.           6 February, 1995  -  fixed bug with detection of CD-ROM drives,
  25.                                thanx to Ralf Quint
  26.           7 March,    1995  -  released version 2. Mr. Byte made some
  27.                                modifications to the entire code
  28. }
  29. (**** General notes:
  30.  
  31.   This code can be easily ported to C/C++, because most of it is written in
  32.   inline assembler. Just convert @@-style labels to __ and add "asm"s where
  33.   needed. Note, that the call to checkStacker4 cannot be made in C/C++ the way
  34.   it is done here (at least in Borland C++), you should do it like this:
  35.  
  36.   unsigned char GetDriveType( void )
  37.   {
  38.   register unsigned char temp;
  39.   ...
  40.   mov    temp,Drive        // passing the parameter
  41.     }
  42.   checkStacker4(temp);
  43. asm {
  44.   ...
  45.   }
  46.  
  47.   Warning: the entire code require 2048 stack space.
  48.  
  49.   end of General notes ****)
  50.  
  51. {$S-,R-,I-,X+}
  52. { disable stack, I/O and range checking, enable extended syntax }
  53.  
  54. unit DrvTypes;
  55. { drive types }
  56.  
  57. interface
  58.  
  59. const
  60.   dtError      = $00; { Invalid drive, letter not assigned }
  61.   dtFixed      = $01; { Fixed drive }
  62.   dtRemovable  = $02; { Removeable (floppy, etc.) drive }
  63.   dtRemote     = $03; { Remote (network) drive }
  64.   dtCDROM      = $04; { MSCDEX V2.00+ driven CD-ROM drive }
  65.   dtDblSpace   = $05; { DoubleSpace compressed drive }
  66.   dtSUBST      = $06; { SUBST'ed drive }
  67.   { dudes, where are Stacker 1,2,3 check-routines? }
  68.   dtStacker4   = $08; { Stacker 4 compressed drive }
  69.   dtRAMDrive   = $09; { RAM drive }
  70.   dtDublDisk   = $0A; { Vertisoft DoubleDisk 2.6 compressed drive }
  71.   dtBernoully  = $0B; { IOmega Bernoully drive }
  72.   dtDiskreet   = $0C; { Norton Diskreet drive }
  73.   dtSuperStor  = $0D; { SuperStor compressed drive }
  74.  
  75.   checkABforStacker : Boolean = False;
  76.  { Controls whether we should check drives A: and B: for Stacker volumes.
  77.    There is no convenient way to determine if drive is Stacker volume (like
  78.    for DoubleSpace/Drive*Space volumes), so we should use absolute disk read
  79.    function to do it. Drives A: and B: are typically floppy drives, thus one
  80.    may not want to check them causing reads from floppies (which could be
  81.    not inserted at all). /Bobby Z., 29/11/94 }
  82.  
  83. function GetDriveType(Drive : byte) : byte;
  84. function CountValidDrives : byte;
  85.  
  86. implementation
  87.  
  88. type
  89.     ControlBlk25 = record    { control block for INT 25 extended call }
  90.             StartSector : LongInt; { start sector to read }
  91.             Count        : Word;    { number of sectors to read }
  92.             BufferOffs  : Word;    { data buffer offset }
  93.             BufferSeg   : Word;    { data buffer segment }
  94.                end;
  95.  
  96. function checkStacker4( Drive : Byte ) : Boolean; near; assembler;
  97. { returns True if Drive is Stacker 4 compressed volume, False otherwise.
  98.   This also may return True with previous versions of Stacker - I didn't
  99.   check it. /Bobby Z. 29/11/94 }
  100.  
  101. var CB   : ControlBlk25;
  102.     Boot : array[1..512] of Byte;
  103. asm
  104.     push    ds
  105.     mov    al,Drive
  106.     cmp    checkABforStacker,1 { check A: & B: for Stacker volume? }
  107.     jz    @@1
  108.     cmp    al,1
  109.     ja    @@1
  110.     sub    al,al
  111.     jmp    @@Q
  112. @@1:
  113.     push    ss
  114.     pop    ds
  115.     lea    bx,CB
  116.     sub    ax,ax
  117.     mov    word ptr ds:ControlBlk25[bx].StartSector,ax
  118.     mov    word ptr ds:ControlBlk25[bx].StartSector[2],ax
  119.     mov    word ptr ds:ControlBlk25[bx].Count,1
  120.     lea    dx,Boot
  121.     mov    word ptr ds:ControlBlk25[bx].BufferOffs,dx
  122.     mov    word ptr ds:ControlBlk25[bx].BufferSeg,ds
  123.     mov    al,Drive
  124.     sub    cx,cx
  125.     dec    cx
  126.     mov    si,sp
  127.     int    25h
  128.     cli
  129.     mov    sp,si
  130.     sti
  131.     pushf
  132.     lea    si,Boot
  133.     add    si,1F0h        { Stacker signature CD13CD14CD01CD03 should }
  134.     sub    al,al        { appear at offset 1F0 of boot sector.      }
  135.     popf
  136.     jc    @@Q        { was error reading boot sector - assume    }
  137.                 { not Stacker drive                         }
  138.     cmp    word ptr ds:[si],13CDh
  139.     jnz    @@Q
  140.     cmp    word ptr ds:[si][2],14CDh
  141.     jnz    @@Q
  142.     cmp    word ptr ds:[si][4],01CDh
  143.     jnz    @@Q
  144.     cmp    word ptr ds:[si][6],03CDh
  145.     jnz    @@Q
  146.     mov    al,1
  147. @@Q:
  148.     pop    ds
  149. end; { checkStacker4 }
  150.  
  151. function checkDiskreet(Drive : byte) : boolean; near; assembler;
  152. { Returns True if Drive is Norton Diskreet drive, otherwise it returns False }
  153. type
  154.   TDiskreetPacket = record
  155.     Header : array [1..6] of byte;
  156.     Drive  : char;
  157.     Size   : longint
  158.   end;
  159. const DrvName : PChar = '@DSKREET'; {-Diskreet driver name}
  160. var Packet : TDiskreetPacket;
  161. asm
  162.         push    ds
  163.         mov     ax,0FE00h
  164.         mov     di,'NU'   { 4E55h='NU' }
  165.         mov     si,'DC'   { 4443h='DC' }
  166.         int     2Fh
  167.         or      al,al     { check for zero }
  168.         je      @@2
  169.         cmp     al,1      { check for 1 }
  170.         je      @@2
  171. @@1:
  172.         sub     al,al      { return False }
  173.         jmp     @@4
  174. @@2:
  175.         lds     dx,DrvName
  176.         mov     ax,3D02h
  177.         int     21h
  178.         jc      @@1
  179.         mov     bx,ax
  180.         mov     ax,seg [Packet]
  181.         mov     ds,ax
  182.         mov     dx,offset [Packet]
  183.         mov     es,ax
  184.         mov     di,dx
  185.         mov     cx,type TDiskreetPacket
  186.         sub     al,al
  187.         cld
  188.         rep     stosb     { initialize Packet fields }
  189.         mov     di,offset [Packet.Header]
  190.         mov     ax,12FFh  { store first two bytes in Packet header }
  191.         stosw
  192.         mov     di,offset [Packet.Drive]
  193.         mov     al,Drive
  194.         add     al,64     { convert drive number to drive letter }
  195.         stosb             { store drive letter }
  196.         mov     ax,4403h  { ready to send Diskreet Packet }
  197.         mov     cx,7
  198.         mov     si,'dc'   { 6463h = 'dc' }
  199.         mov     di,'NU'   { 4E55h = 'NU' }
  200.         int     21h       { assuming ds=seg [Packet], dx=offset [Packet],
  201.                             bx=Handle }
  202.         mov     ah,3Eh
  203.         int     21h       { close device }
  204.         mov     si,offset [Packet.Size]
  205.         lodsw
  206.         or      ax,ax
  207.         jnz     @@3
  208.         lodsw
  209.         or      ax,ax
  210.         jz      @@1
  211. @@3:
  212.         mov     al,True   { return True }
  213. @@4:
  214.         pop     ds
  215. end; { checkDiskreet }
  216.  
  217. function checkSuperStor(Drive : byte) : boolean; near; assembler;
  218. type
  219.   TSSPacket = record
  220.     Sign  : word;
  221.     Sign1 : word;
  222.     P     : pointer;
  223.     Res   : array [1..4] of byte
  224.   end;
  225. var
  226.   Packet : TSSPacket;
  227. asm
  228.         push    ds
  229.         mov     ax,seg [Packet]
  230.         mov     es,ax
  231.         mov     di,offset [Packet]
  232.         mov     cx,type TSSPacket
  233.         cld
  234.         rep     stosb   { initialize SStor Packet structure }
  235.         mov     di,offset [Packet.Sign]
  236.         mov     ax,0AA55h
  237.         stosw             { init Packet.Sign }
  238.         mov     ax,0201h
  239.         stosw             { init Packet.Sign1 }
  240.         mov     ax,4404h
  241.         mov     dx,seg [Packet]
  242.         mov     ds,dx
  243.         mov     dx,offset [Packet]
  244.         mov     cx,12
  245.         mov     bl,Drive
  246.         int     21h
  247.         jc      @@2          { if error then quit }
  248.         mov     si,offset [Packet.Sign]
  249.         lodsw
  250.         or      ax,ax        { if Packet.Sign<>0 then quit }
  251.         jnz     @@2
  252.         lodsw
  253.         cmp     ax,0201h     { if Packet.Sign1<>0201h then quit }
  254.         jne     @@2
  255.         les     di,[Packet.P]
  256.         mov     ax,[es:di+5Dh]
  257.         test    ax,40h       { host drive? }
  258.         jz      @@2
  259.         mov     cl,byte ptr es:[di+24h]
  260.         add     cl,'A'
  261.         mov     ah,30h
  262.         int     21h
  263.         cmp     ah,4
  264.         jb      @@1
  265.         inc     di
  266. @@1:
  267.         les     di,dword ptr es:[di+5Fh]
  268.         mov     bl,[es:di]
  269.         add     bl,'A'
  270.         cmp     cl,Drive   { ????? I don't know whether bl or cl is a host
  271.                              SStor drive... }
  272.         jne     @@2
  273.         mov     al,True   { return True }
  274.         jmp     @@3
  275. @@2:
  276.         sub     al,al     { return False }
  277. @@3:
  278.         pop     ds
  279. end; { checkSuperStor }
  280.  
  281. function GetDriveType; assembler;
  282. { Detects the type for a specified drive. Drive is a drive number to detect the
  283.   type for (0=detect current (default) drive, 1=A, 2=B, 3=C...)
  284.  
  285.   Returns: One of the dtXXX-constants.
  286.  
  287.   Note: Function will work under DOS version 3.30 or later
  288.         Also should work under DPMI and Windows.
  289. }
  290.  
  291. asm
  292.     cmp    Drive,0
  293.     jne    @@1
  294.     mov    ah,19h    { get active drive number in al }
  295.     int    21h
  296.     mov    Drive,al
  297.     inc    Drive
  298. @@1:
  299.         push    word ptr [Drive]
  300.         call    checkDiskreet
  301.         or    al,al
  302.     jz    @CDROMcheck
  303.     mov    bl,dtDiskreet
  304.         jmp     @@7
  305. @CDROMcheck:
  306.     mov    ax,1500h  { check for CD-ROM v2.00+ }
  307.     sub    bx,bx
  308.     int    2Fh
  309.     or    bx,bx
  310.     jz    @@2
  311.     mov    ax,150Bh
  312.     sub    ch,ch
  313.     mov    cl,Drive
  314.         dec     cl      { bug fixed with CD-ROM drives, thanx to Ralf Quint }
  315.     int    2Fh     { drives for this function start with 0 for A: }
  316.     cmp    bx,0ADADh
  317.     jne    @@2
  318.     or    ax,ax
  319.     jz    @@2
  320.     mov    bl,dtCDROM
  321.     jmp    @@7
  322. @@2:
  323.     mov    ax,4409h { check for SUBST'ed drive }
  324.     mov    bl,Drive
  325.     int    21h
  326.     jc    @DblSpaceChk
  327.     test    dh,80h
  328.     jz    @DblSpaceChk
  329.     mov    bl,dtSUBST
  330.     jmp    @@7
  331. @DblSpaceChk:
  332.     mov    ax,4A11h  { check for DoubleSpace drive }
  333.     mov    bx,1
  334.     mov    dl,Drive
  335.     dec    dl
  336.     int    2Fh
  337.     or    ax,ax     { is DoubleSpace loaded? }
  338.     jnz    @@3
  339.     cmp    dl,bl     { if a host drive equal to compressed, then get out... }
  340.     je    @@3
  341.     test    bl,80h    { bit 7=1: DL=compressed,BL=host
  342.                                  =0: DL=host,BL=compressed }
  343.     jz    @SStorChk   { so avoid host drives, assume host=fixed :) }
  344.     inc    dl
  345.     cmp    Drive,dl
  346.     jne    @SStorChk
  347.     mov    bl,dtDblSpace
  348.     jmp    @@7
  349. @SStorChk:
  350.         push    word ptr [Drive]
  351.         call    checkSuperStor
  352.         or    al,al
  353.     jz    @@3
  354.     mov    bl,dtSuperStor
  355.         jmp     @@7
  356. @@3:
  357.     mov    ax,4409h     { check for remote drive }
  358.     mov    bl,Drive
  359.     int    21h
  360.     jc    @@5
  361.     and    dh,10h
  362.     jz    @@4
  363.     mov    bl,dtRemote
  364.     jmp    @@7
  365. @@4:
  366.     mov    al,Drive     { check for Stacker 4 volume }
  367.     or    al,al
  368.     jz    @@getDrv
  369.     dec    al
  370. @@goStac:
  371.     push    ax
  372.     call    checkStacker4
  373.     or    al,al
  374.     jz    @@8
  375.     mov    bl,dtStacker4
  376.     jmp    @@7
  377. @@8:
  378.         mov     ax,4408h     { check for fixed (hard) drive }
  379.         mov     bl,Drive
  380.         int     21h
  381.         jc      @@5
  382.         or      al,al
  383.         jz      @@6
  384.         push    ds           { check for RAM drive }
  385.         mov     ax,ss
  386.         mov     ds,ax
  387.         mov     si,sp
  388.         sub     sp,28h         { allocate 28h bytes on stack }
  389.         mov     dx,sp
  390.         mov     ax,440Dh     { generic IOCTL }
  391.         mov     cx,860h      { get device parameters }
  392.         int     21h          { RAMDrive and VDISK don't support this command }
  393.     jc    @@cleanup
  394.     pushf
  395.     mov    di,dx
  396.     cmp    byte ptr ds:[di+6],0F8h    { DoubleDisk returns 0F8h in media type}
  397.     jz    @@dubldsk        { field of BPB if drive in question is }
  398.                     { compressed }
  399.     popf
  400.     jmp    @@cleanup
  401. @@dubldsk:
  402.     popf
  403.     mov    bl,dtDublDisk
  404.     mov    sp,si
  405.     pop    ds
  406.     jmp    @@7
  407. @@cleanup:
  408.         mov     sp,si
  409.         pop     ds
  410.         mov     bl,dtRAMDrive
  411.         jc      @@7
  412.     push    ds
  413.     mov    ah,1Ch            { this function works _really_ slowly }
  414.     mov    dl,Drive        { get media descriptor pointer }
  415.     int    21h
  416.     cmp    byte ptr ds:[bx],0FDh
  417.     pop    ds
  418.     jnz    @@fixed
  419.     push    ds
  420.     mov    ah,32h            { get BPB pointer }
  421.     mov    dl,Drive
  422.     int    21h
  423.     cmp    byte ptr ds:[bx+0Bh],2    { Sectors per FAT is more than 2 for }
  424.     pop    ds            { Bernoully drives }
  425.     jz    @@fixed
  426.     mov    bl,dtBernoully
  427.     jmp    @@7
  428. @@fixed:
  429.         mov     bl,dtFixed
  430.         jmp     @@7
  431. @@5:
  432.     sub    bl,bl        { mov bl,dtError cuz dtError=0 }
  433.     jmp    @@7
  434. @@getDrv:
  435.     mov    ah,19h
  436.     int    21h
  437.     jmp    @@goStac        
  438. @@6:
  439.     mov    bl,dtRemovable   { else - removeable media }
  440. @@7:
  441.     mov    al,bl
  442. end; { GetDriveType }
  443.  
  444. function CountValidDrives; assembler;
  445. { - returns number of assigned letters in system }
  446. var Drive, Count : byte;
  447. asm
  448.         mov     Drive,1
  449.         mov     Count,0
  450. @@1:
  451.         push    word ptr Drive
  452.         call    GetDriveType
  453.         or      al,dtError
  454.         jz      @@2
  455.         inc     Count
  456. @@2:
  457.         inc     Drive
  458.         cmp     Drive,26
  459.         jbe     @@1
  460.         mov     al,Count
  461. end;
  462.  
  463. end.
  464.